#ifndef SPHERE_H
#define SPHERE_H
#include "hittable.h"
#include "ray.h"
class sphere: public hittable {
    public:
    // 构造函数，初始化球心坐标和半径
    sphere(const point3& center ,double radius):center(center),radius(std::fmax(0,radius)){}
    // 重写hit函数，判断射线是否与球相交
    bool hit (const ray& r , double ray_min, double ray_max,hit_record& rec)const override{
        // 计算射线原点到球心的向量
        vec3 oc = center  - r.origin();
        // 计算射线方向的长度平方
        auto a  = r.direction().length_squared();
        // 计算射线方向与射线原点到球心的向量的点积
        auto h= dot(r.direction(),oc);
        // 计算射线原点到球心的向量的长度平方减去半径的平方
        auto c = oc.length_squared() - radius * radius;
        // 计算判别式
        auto discriminant = h*h -a* c;
        // 如果判别式小于0，说明射线与球不相交
        if(discriminant < 0){
            return false;
        }
        // 计算判别式的平方根
        auto sqrtd = std::sqrt(discriminant);
        // 计算交点的t值
        auto root = (h - sqrtd)/ a;
        // 如果t值不在射线的范围内，重新计算t值
        if(root < ray_min || ray_max <= root){
            root = (h + sqrtd)/ a;
            // 如果t值仍然不在射线的范围内，说明射线与球不相交
            if(root <= ray_min || ray_max < root){
                return false;
            }
        }
        // 记录交点的t值
        rec.t = root;
        // 计算交点坐标
        rec.p = r.at(rec.t);// 交点

        // 计算交点的法线
        rec.normal = (rec.p -center) / radius;// 法线
        // 设置交点的法线方向
        rec.set_face_normal(r,rec.normal);
        
        // 返回射线与球相交
        return true;

    }
    private:
    // 球心坐标
    point3 center;
    // 球的半径
    double radius;
};

#endif